package com.dankegongyu.lib.common.paging;

import com.dankegongyu.lib.common.base.BaseModel;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * https://ke.qq.com/course/468573?tuin=7f00b635
 *
 * @author wpq
 * @version 1.0
 */
public abstract class BasePagingModel<T> extends BaseModel {

    private int mFirstPage;
    private int mCurrentPage;
    private ReferenceQueue<BasePagingModelListener<T>> mReferenceQueue;
    private ConcurrentLinkedQueue<WeakReference<BasePagingModelListener<T>>> mWeakListenerList;

    public BasePagingModel() {
        this.mFirstPage = getFirstPage();
        this.mCurrentPage = this.mFirstPage;
        mReferenceQueue = new ReferenceQueue<>();
        mWeakListenerList = new ConcurrentLinkedQueue<>();
    }

    protected abstract int getFirstPage();

    public int getCurrentPage() {
        return Math.max(mCurrentPage, mFirstPage);
    }

    private void setCurrentPage(int page) {
        mCurrentPage = Math.max(page, mFirstPage);
    }

    public boolean isFirstPage() {
        return mCurrentPage == mFirstPage;
    }

    protected void refresh() {
        setCurrentPage(mFirstPage);
        loadPagingData();
    }

    protected void loadMore() {
        setCurrentPage(mCurrentPage + 1);
        loadPagingData();
    }

    protected abstract void loadPagingData();

    public void register(BasePagingModelListener<T> listener) {
        if (listener == null) {
            return;
        }
        synchronized (this) {
            // 每次注册的时候清理已经被系统回收的对象
            Reference<? extends BasePagingModelListener<T>> releaseListener;
            while ((releaseListener = mReferenceQueue.poll()) != null) {
                //noinspection SuspiciousMethodCalls
                mWeakListenerList.remove(releaseListener);
            }

            for (WeakReference<BasePagingModelListener<T>> weakListener : mWeakListenerList) {
                BasePagingModelListener item = weakListener.get();
                if (item == listener) {
                    return;
                }
            }
            WeakReference<BasePagingModelListener<T>> weakListener = new WeakReference<>(listener, mReferenceQueue);
            mWeakListenerList.add(weakListener);
        }
    }

    public void unregister(BasePagingModelListener<T> listener) {
        if (listener == null) {
            return;
        }
        synchronized (this) {
            Iterator<WeakReference<BasePagingModelListener<T>>> it = mWeakListenerList.iterator();
            //noinspection WhileLoopReplaceableByForEach
            while (it.hasNext()) {
                WeakReference<BasePagingModelListener<T>> weakListener = it.next();
                BasePagingModelListener item = weakListener.get();
                if (item == listener) {
                    mWeakListenerList.remove(weakListener);
                    break;
                }
            }
        }
    }

    /**
     * 分页数据请求成功
     *
     * @param totalCount  总数
     * @param dataPaged   当前页数据
     * @param hasNextPage 是否有下一页
     */
    protected void loadSuccess(int totalCount, List<T> dataPaged, boolean hasNextPage) {
        synchronized (this) {
            PagingData<T> pagingData = new PagingData<T>(totalCount, dataPaged, isFirstPage(), hasNextPage);
            for (WeakReference<BasePagingModelListener<T>> weakListener : mWeakListenerList) {
                BasePagingModelListener<T> item = weakListener.get();
                if (item != null) {
                    item.onPagingLoadSuccess(this, pagingData);
                }
            }
        }
    }

    protected void loadFailure(String errorMessage) {
        synchronized (this) {
            for (WeakReference<BasePagingModelListener<T>> weakListener : mWeakListenerList) {
                BasePagingModelListener<T> item = weakListener.get();
                if (item != null) {
                    item.onPagingLoadFailure(this, errorMessage, isFirstPage());
                }
            }
        }

        setCurrentPage(mCurrentPage - 1); // 加载更多失败页面减1
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}
